#include <xpp/net/TcpServer.h>
#include <xpp/net/Tcp4Address.h>
#include <xpp/net/Tcp6Address.h>
#include <xp/bas/stdio.h>
#include <xp/bas/locale.h>

#ifdef __linux
#include <mcheck.h>
#endif

using namespace xpp::net;

class MyServer: public TcpServer {
public:
	MyServer (const TcpAddress& address): TcpServer (address) 
	{
	}
	
	int handle_client (TcpSocket* sock, TcpAddress* addr) 
	{
		xp_printf (XP_TEXT("connected...\n"));

		/*
		TcpAddress a;
		if (sock->getAddress (&a) == -1) {
			xp_printf (XP_TEXT("failed to retrieve address\n"));
		}
		else {
			xp_printf (XP_TEXT("destination: family = %d, host: %s, service: %s\n"),
				a.family(), (const xp_char_t*)a.hostName(), 
				(const xp_char_t*)a.numericService());
		}
		*/

		/*
		TcpAddress peer;
		if (sock->getPeerAddress (&peer) == -1) {
			xp_printf (XP_TEXT("failed to retrieve peer address\n"));
		}
		else {
			xp_printf (XP_TEXT("source: family = %d, host: %s, service: %s\n"),
				peer.family(), (const xp_char_t*)peer.hostName(),
				(const xp_char_t*)peer.numericService());
		}
		*/

		char buf[1000];
		xp_ssize_t n;
		while ((n = sock->receive (buf, sizeof(buf) - 1)) > 0) {
			buf[n] = '\0';
#ifdef XP_CHAR_IS_WCHAR
			xp_char_t wbuf[1000];		
			xp_mcstowcs (buf, wbuf, xp_countof(wbuf));
			xp_printf (XP_TEXT("read %d bytes: [%s]\n"), n, wbuf);
#else
			xp_printf (XP_TEXT("read %d bytes: [%s]\n"), n, buf);
#endif
		}

		xp_printf (XP_TEXT("disconnected.. (%d)\n"), n);
		return 0;	
	}
};

#ifdef __cplusplus
extern "C" { int xp_main (int argc, xp_char_t* argv[]); }
#endif

int xp_main (int argc, xp_char_t* argv[])
{
#ifdef __linux
	mtrace ();
#endif

	if (xp_setlocale () == -1) {
		xp_printf (XP_TEXT("usage: cannot set locale\n"), argv[0]);
		return -1;
	}

	if (argc != 2) {
		xp_printf (XP_TEXT("usage: %s service\n"), argv[0]);
		return -1;
	}

	if (Socket::startup () == -1) {
		xp_printf (XP_TEXT("cannot start up socket subsystem\n"));
		return -1;
	}

	TcpAddress addr;
	if (TcpAddress::resolve (argv[1], &addr) == -1) {
	//if (TcpAddress::resolve (argv[1], XP_TEXT("localhost"), &addr) == -1) {
		xp_printf (XP_TEXT("cannot resolve [%s]\n"), argv[0]);
		Socket::cleanup ();
		return -1;
	}

	MyServer server (addr);
	server.setMaxConnections (2); // only one connection is allowed
	int err_code;
	if (server.startServing (&err_code) == -1) {
		xp_printf (XP_TEXT("failed to start the server: %d\n"), err_code);
	}

	Socket::cleanup ();
	return 0;
}
